package cn.e4j.core.util;

import cn.e4j.core.common.exception.BizExceptionEnum;
import cn.e4j.model.exception.ServiceException;
import cn.e4j.modular.system.entity.SysModule;
import cn.e4j.modular.system.entity.SysOrg;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 * 树结构组装
 * @author wenchuan.li
 * @date 2018/12/10 12:58
 */
public class TreeUtil {

    /**
     * 生成tree数据结构
     * @param nodeList 需要根据 parentid字段 排序（升序）
     * @param root
     */
    public static void generateTree(List<Map<String,Object>> nodeList, Map<String,Object> root){
        // 保存未找到父节点的数据
        List<Map<String,Object>> tempList = new ArrayList<>();
        // 保存已找到父节点的数据
        Map<String, Map<String,Object>> temp = new HashMap<>();
        temp.put((String)root.get("id"), root);
        root.put("children", new ArrayList<>());

        nodeList.forEach(result->{
            String parentid =(String)result.get("parentid");
            if(temp.containsKey(parentid)){
                Map<String,Object> pItem = temp.get(parentid);
                if(!pItem.containsKey("children")){
                    pItem.put("children", new ArrayList<>());
                }
                temp.put((String)result.get("id"), result);
                ((List<Map<String,Object>>)pItem.get("children")).add(result);
            }else{
                tempList.add(result);
            }
        });

        tempList.forEach(result->{
            String parentid =(String)result.get("parentid");
            if(temp.containsKey(parentid)){
                Map<String,Object> pItem = temp.get(parentid);
                if(!pItem.containsKey("children")){
                    pItem.put("children", new ArrayList<>());
                }
                temp.put((String)result.get("id"), result);
                ((List<Map<String,Object>>)pItem.get("children")).add(result);
            }
        });

//        Iterator<Map<String,Object>> it = nodeList.iterator();
//        while(it.hasNext()){
//            Map<String,Object> node = it.next();
//            if(node.get("parentid").toString().equals(root.get("id").toString())){
//                if(!root.containsKey("children")){
//                    root.put("children", new ArrayList<>());
//                }
//                ((List<Map<String,Object>>)root.get("children")).add(node);
//                generateTree(nodeList,node);
//            }
//        }
    }

    /**
     * tree 2
     * @param resultList
     * @param item
     */
    public static void eachChildrens(List<Map<String,Object>> resultList, Map<String,Object> item){
        resultList.forEach(result->{
            if(result.get("id").toString().equals(item.get("parentid").toString())){
                if(!result.containsKey("children")){
                    result.put("children", new ArrayList<>());
                }
                ((List<Map<String,Object>>)result.get("children")).add(item);
            }else{
                if(result.containsKey("children")) {
                    eachChildrens((List<Map<String,Object>>)result.get("children"), item);
                }
            }
        });
    }

    private static void sortChildren(List<Map<String,Object>> resultList) {
        resultList.forEach(result->{
            if(result.containsKey("children")){
               List childrenList = (ArrayList) result.get("children");
               childrenList.sort(new Comparator<Map<String, Object>>() {
                   @Override
                   public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                       long no1 = (Long)(o1.get("sort_no")==null?0L:o1.get("sort_no"));
                       long no2 = (Long)(o2.get("sort_no")==null?0L:o2.get("sort_no"));
                       if(no1 < no2 ){
                           return -1;
                       }else if(no1 == no2) {
                           return 0;
                       }else {
                           return 1;
                       }
                   }
               });
               sortChildren(childrenList);
            }else{
                return;
            }
        });
    }

    /**
     * 菜单tree
     * @param sysOrgs
     * @return
     */
    public static List<Map<String,Object>> orgsTree(List<SysOrg> sysOrgs){
        List<Map<String,Object>> resultList = new ArrayList<>();
        Map<String,Object> result = null;
        for (SysOrg sysOrg : sysOrgs){
            if(result==null){
                result = new HashMap();
                result.put("id", sysOrg.getID());
                result.put("name", sysOrg.getNAME());
                result.put("code",sysOrg.getCASCADE_ID());
                result.put("children", new ArrayList<>());
                result.put("sort_no",sysOrg.getSORT_NO());
                resultList.add(result);
            }else{
                Map<String,Object> item = new HashMap();
                item.put("id", sysOrg.getID());
                item.put("name", sysOrg.getNAME());
                item.put("parentid", sysOrg.getPARENT_ID());
                item.put("code",sysOrg.getCASCADE_ID());
                item.put("sort_no",sysOrg.getSORT_NO());
                eachChildrens(resultList, item);
            }
        }
        sortChildren(resultList);
        return resultList;
    }


    public static List<Map<String,Object>> modulesTree(List<SysModule> sysModules){
        List<Map<String,Object>> resultList = new ArrayList<>();
        Map<String,Object> result = null;
        for (SysModule sysModule : sysModules){
            if(result==null){
                result = new HashMap();
                result.put("id", sysModule.getID());
                result.put("name", sysModule.getNAME());
                result.put("code",sysModule.getCASCADE_ID());
                result.put("children", new ArrayList<>());
                resultList.add(result);
            }else{
                Map<String,Object> item = new HashMap();
                item.put("id", sysModule.getID());
                item.put("name", sysModule.getNAME());
                item.put("parentid", sysModule.getPARENT_ID());
                item.put("code",sysModule.getCASCADE_ID());
                eachChildrens(resultList, item);
            }
        }
        return resultList;
    }

    /**
     * 生成树路径ID，如：01.01.01
     *
     * @param curMaxNode
     *            本级当前最大节点ID，如果要生成本级第一个节点则传XX.XX.00(XX.XX为父节点ID)。
     * @param maxValue
     *            本级节点ID允许的最大值
     * @return
     */
    public static String genCascadeTreeId(String curMaxNode, int maxValue) {
        String prefix = StringUtils.substringBeforeLast(curMaxNode, ".");
        String last = StringUtils.substringAfterLast(curMaxNode, ".");
        if (last.isEmpty()) {
            throw new ServiceException(BizExceptionEnum.TREE_ERROR);
        }
        int intLast = Integer.valueOf(last);
        if (intLast == maxValue || intLast > maxValue) {
            throw new ServiceException(BizExceptionEnum.TREE_NO_SPACE);
        }
        String thisNode = String.valueOf(intLast + 1);
        thisNode = StringUtils.leftPad(thisNode, String.valueOf(maxValue).length(), "0");
        return prefix + "." + thisNode;
    }

}
